﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor.Utils
{
    public static class Text
    {
        public static List<TextPiece> SplitToPiecesByRegex(string regex, string source)
        {
            if (string.IsNullOrEmpty(regex)) return new List<TextPiece>();
            if (string.IsNullOrEmpty(source)) return new List<TextPiece>();

            var list = new List<TextPiece>();
            try
            {
                var reg = new Regex(regex);
                var matches = reg.Matches(source);
                if (matches.Count <= 0)
                {
                    list.Add(new TextPiece()
                    {
                        StartIndex = 0,
                        EndIndex = source.Length,
                        IsMartchText = false,
                        SourceText = source,
                        ReplacedText = source,
                    });
                    return list;
                }

                int newStartIndex = 0;
                foreach (Match match in matches)
                {
                    if (match.Index > 0)
                    {
                        var piece = source.Substring(newStartIndex, match.Index - newStartIndex);
                        list.Add(new TextPiece()
                        {
                            StartIndex = newStartIndex,
                            EndIndex = match.Index,
                            IsMartchText = false,
                            SourceText = piece,
                            ReplacedText = piece,
                        });
                    }

                    list.Add(new TextPiece()
                    {
                        StartIndex = match.Index,
                        EndIndex = match.Index + match.Length,
                        IsMartchText = true,
                        SourceText = match.Value,
                    });
                    newStartIndex = match.Index + match.Length;
                }

                if (matches.Count > 0)
                {
                    var lastMatch = matches[matches.Count - 1];
                    if (lastMatch.Index < source.Length)
                    {
                        var nextIndex = lastMatch.Index + lastMatch.Length;
                        var lastPiece = source.Substring(nextIndex);
                        list.Add(new TextPiece()
                        {
                            StartIndex = nextIndex,
                            EndIndex = source.Length,
                            IsMartchText = false,
                            SourceText = lastPiece,
                            ReplacedText = lastPiece,
                        });
                    }
                }

                return list;
            }
            catch(Exception ex)
            {
                list.Clear();
                list.Add(new TextPiece()
                {
                    StartIndex = 0,
                    EndIndex = source.Length,
                    IsMartchText = false,
                    SourceText = source,
                    ReplacedText = source,
                });
                return list;
            }
        }

        public static List<TextPiece> SplitToPiecesByRegex(string regex, string source, bool muiltiLines, bool ignoreCase)
        {
            if (string.IsNullOrEmpty(regex)) return new List<TextPiece>();
            if (string.IsNullOrEmpty(source)) return new List<TextPiece>();

            var list = new List<TextPiece>();
            try
            {

                var options = new RegexOptions();
                if (muiltiLines)
                {
                    options |= RegexOptions.Multiline;
                }

                if (ignoreCase)
                {
                    options |= RegexOptions.IgnoreCase;
                }

                var reg = new Regex(regex,options);

                var matches = reg.Matches(source);
                if (matches.Count <= 0)
                {
                    list.Add(new TextPiece()
                    {
                        StartIndex = 0,
                        EndIndex = source.Length,
                        IsMartchText = false,
                        SourceText = source,
                        ReplacedText = source,
                    });
                    return list;
                }

                int newStartIndex = 0;
                foreach (Match match in matches)
                {
                    if (match.Index > 0)
                    {
                        var piece = source.Substring(newStartIndex, match.Index - newStartIndex);
                        list.Add(new TextPiece()
                        {
                            StartIndex = newStartIndex,
                            EndIndex = match.Index,
                            IsMartchText = false,
                            SourceText = piece,
                            ReplacedText = piece,
                        });
                    }

                    list.Add(new TextPiece()
                    {
                        StartIndex = match.Index,
                        EndIndex = match.Index + match.Length,
                        IsMartchText = true,
                        SourceText = match.Value,
                    });
                    newStartIndex = match.Index + match.Length;
                }

                if (matches.Count > 0)
                {
                    var lastMatch = matches[matches.Count - 1];
                    if (lastMatch.Index < source.Length)
                    {
                        var nextIndex = lastMatch.Index + lastMatch.Length;
                        var lastPiece = source.Substring(nextIndex);
                        list.Add(new TextPiece()
                        {
                            StartIndex = nextIndex,
                            EndIndex = source.Length,
                            IsMartchText = false,
                            SourceText = lastPiece,
                            ReplacedText = lastPiece,
                        });
                    }
                }

                return list;
            }
            catch (Exception ex)
            {
                list.Clear();
                list.Add(new TextPiece()
                {
                    StartIndex = 0,
                    EndIndex = source.Length,
                    IsMartchText = false,
                    SourceText = source,
                    ReplacedText = source,
                });
                return list;
            }
        }

        public static Match Match(string src, string reg, bool muiltiLine = false)
        {
            if (string.IsNullOrEmpty(src)) return null;

            Regex regex;
            if (muiltiLine)
            {
                regex = new Regex(reg, RegexOptions.Multiline);
            }
            else
            {
                regex = new Regex(reg);
            }

            return regex.Match(src);
        }

        public static MatchCollection Matches(string src, string reg, bool muiltiLine = false)
        {
            if (string.IsNullOrEmpty(src)) return null;

            Regex regex;
            if (muiltiLine)
            {
                regex = new Regex(reg, RegexOptions.Multiline);
            }
            else
            {
                regex = new Regex(reg);
            }

            return regex.Matches(src);
        }

        public static string JoinReplacedList(List<TextPiece> pieces)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var piece in pieces)
                sb.Append(piece.ReplacedText);
            return sb.ToString();
        }

        /// <summary>
        /// 源码来自：https://blog.csdn.net/studyregister/article/details/7076160 ，有修改
        /// 原作者应该是：Sundays
        /// </summary>
        /// <param name="text"></param>
        /// <param name="fontSize"></param>
        /// <param name="fontFamily"></param>
        /// <returns></returns>
        public static double MeasureTextWidth(string text, double fontSize, string fontFamily)
        {
            FormattedText formattedText = new FormattedText(
            text,
            System.Globalization.CultureInfo.InvariantCulture,
            FlowDirection.LeftToRight,
            new Typeface(fontFamily.ToString()),
            fontSize,
            Brushes.Black
            );
            return formattedText.WidthIncludingTrailingWhitespace;
        }
    }

    public class TextPiece
    {
        public int StartIndex { get; set; }
        public int EndIndex { get; set; }
        public int Length { get { return EndIndex - StartIndex; } }
        public bool IsMartchText { get; set; }
        public string SourceText { get; set; }
        public string ReplacedText { get; set; }
    }

}
